昨天談完了Quasar 框架 CSS初始化的部分
今天來談Quasar 框架 js初始化的部分
一、Quasar 初始化的流程
二、Boot 在專案的初始化流程應用示例
三、ESModule 常用的 import 和 export 方式
四、總結
五、延伸閱讀
Boot
在Quasar框架的初始化流程中,是非常重要也非常強大的架構
只要你有ESModule的概念,以及了解Quasar框架的網站初始化流程
你可以很方便的自訂額外的初始化邏輯
在Quasar 的官方文件有提到
使用者一開始進到一個Quasar專案開發的網站
依序的網站初始化流程如下:
In order to better understand how a boot file works and what it does, you need to understand how your website/app boots:
1. Quasar is initialized (components, directives, plugins, Quasar i18n, Quasar icon sets)
2. Quasar Extras get imported (Roboto font – if used, icons, animations, …)
3. Quasar CSS & your app’s global CSS are imported
4. App.vue is loaded (not yet being used)
5. Store is imported (if using Vuex Store in src/store)
6. Router is imported (in src/router)
7. Boot files are imported
8. Router default export function executed
9. Boot files get their default export function executed
(if on Electron mode) Electron is imported and injected into Vue prototype
(if on Cordova mode) Listening for “deviceready” event and only then continuing with following steps
10. Instantiating Vue with root component and attaching to DOM
這邊注意兩個重點:
Boot 的所有程式檔會在 App.vue、Vuex 和 Vue-Router 引入後接著自動引入
換句話說,你可以在Boot存取Vue、Vuex 跟 Vue-Router
Boot 的 export default function 會自動被執行,任何初始化的流程都可以寫在裡面
如同官方文件上的這段程式碼
export default ({ app, router, store, Vue }) => {
// something to do
}
因此,我們可以在Boot做的事情非常多,包括:
我們用Quasar 建立專案時 src/store/module example來示範這個需求
打開src/store/index.js
,將圖中兩處原本的註解拿掉,變成如圖所示:
打開 src/store/module-example/state.js
,在裡面宣告一個token的屬性
export default function () {
return {
token: ''
}
}
src/store/module-example/getters.js
,在裡面寫一個getToken,將Token從Vuex讀取export function getToken (state) {
return state.token
}
src/store/module-example/mutation.js
,在裡面寫一個readToken,用來將Token 存到 example storeexport function readToken (state, token) {
state.token = token
}
src/boot
新增一個localStorage.js
並加到quasar.config.js的boot:[]在localStorage.js
撰寫下面的程式碼
export default ({ app, router, store, Vue }) => {
// 在頁面載入時讀取localStorage裡的token,塞到Vuex
if (localStorage.getItem('token')) {
store.commit('example/readToken', localStorage.getItem('token'))
} else {
store.commit('example/readToken', 'Test001')
}
localStorage.removeItem('token')
// 在頁面重新整理時將vuex裡的token儲存到localStorage裡
window.addEventListener('beforeunload', () => {
localStorage.setItem('token', store.getters['example/getToken'])
})
}
src/pages/Index.vue
,在mounted()加入程式碼<script>
export default {
name: 'DemoPage',
data () {
return {
}
},
mounted () {
console.log(this.$store.getters['example/getToken'])
this.$store.commit('example/readToken', 'Test002')
}
}
</script>
第一次打開網頁時,你會看到console 輸出Test001
把網頁關掉再重開後,會出現Test002
示範了每一次網站打開時,Boot會從localstorage取得上一次的最新值
我們可以在boot設定axios的base url、interceptors
Quasar 專案的src/boot裡面已經有一個axios.js
可以改寫成如下:
import axios from 'axios'
export default ({ app, router, store, Vue }) => {
axios.defaults.baseURL = 'http://api.test.com.tw/'
axios.interceptors.request.use((config) => {
return config
})
Vue.prototype.$axios = axios
}
然後在Index.vue測試axios,看到baseUrl成功的被修改了
<script>
export default {
name: 'DemoPage',
data () {
return {
}
},
mounted () {
this.$axios.post('login', {
username: 'username',
password: 'password'
})
}
}
</script>
例如:Vee Validate
import { ValidationProvider, ValidationObserver, extend, required, email, alpha_num } from 'vee-validate'
export default ({ app, router, store, Vue }) => {
Vue.component('ValidationProvider', ValidationProvider)
Vue.component('ValidationObserver', ValidationObserver)
extend('email', {
...email,
message: '無效的電子郵件格式'
})
extend('required', {
...required,
message: '必填'
})
extend('alpha_num', {
...alpha_num,
message: '只能包含英文字母跟數字'
})
}
例如:CKEditor
import CKEditor from '@ckeditor/ckeditor5-vue'
import ClassicEditor from '@ckeditor/ckeditor5-build-classic'
const editorConfig: {
// 圖文編輯器的預設參數
}
export default ({ app, router, store, Vue }) => {
Vue.use(CKEditor)
}
export { ClassicEditor, editorConfig }
在quasar 的 SSR模式
可以使用在export default function 的參數傳入 ssrContext 操作 Cookie
https://quasar.dev/quasar-cli/developing-ssr/ssr-frequently-asked-questions#Why-doesn%E2%80%99t-importing-Platform-and-Cookies-work%3F
import { Cookies } from 'quasar'
let cookies
export default function ({ app, router, store, Vue, ssrContext }) {
cookies = process.env.SERVER ? Cookies.parseSSR(ssrContext) : Cookies
if (cookies.has('token')) {
store.commit('example/readToken', localStorage.getItem('token'))
}
cookies.remove('store')
}
export { cookies }
要注意的是,有些第三方套件只能在Client端使用
你可以個別設定哪些boot要在server或client時執行:
boot: [
{
server: false, // run on client-side only!
path: '<name>' // references /src/boot/<name>.js
},
{
client: false, // run on server-side only!
path: '<name>' // references /src/boot/<name>.js
}
]
我們在src底下建立一個lib資料夾,並且建立一個test.js
當中包含了這些程式碼
const variable = '安安'
console.log('ㄤㄤ')
export { variable }
export function myFunction () {
console.log(`myFunction 叫${variable}`)
}
export default () => {
console.log(`default 叫${variable}`)
}
以下是在src/pages/Index.vue用不同方式引入:
import test.js並執行test.js裡面,export之外的程式碼
但是無法直接從外部存取test.js的任何變數、外部呼叫test.js的任何函式
//src/pages/Index.vue
<script>
import 'src/lib/test.js'
export default {
name: 'DemoPage',
data () {
return {
}
},
mounted () {
if (variable) {
console.log('Variable', variable)
} else {
console.log('無法存取Variable')
}
}
}
</script>
存檔後,ES Lint 會告訴你,無法存取variable
當你拿掉mounted()
裡面的所有程式碼,會看到輸出了一個ㄤㄤ
import 在 test.js export 的 指定函式
、變數
提供外部使用test.js裡面的指定export
的函式、變數或物件
並執行test.js裡面,export之外的程式碼
export 的時候叫什麼名子
import 的時候就要用什麼名子
//src/pages/Index.vue
<script>
import { variable, myFunction } from 'src/lib/test.js'
export default {
name: 'DemoPage',
data () {
return {
}
},
mounted () {
console.log('Variable', variable)
myFunction()
}
}
</script>
這時候你會看到輸出了ㄤㄤ
、Variable 安安
和myFunction 叫安安
import 在test.js 當中 export default 的 函式
、變數
或 物件
並執行test.js裡面,export之外的程式碼
import 時的 名子自行定義,例如:songla
但是無法直接從外部存取test.js export default
以外的函式、變數 或 物件
//src/pages/Index.vue
<script>
import songla from 'src/lib/test.js'
export default {
name: 'DemoPage',
data () {
return {
}
},
mounted () {
if (variable) {
console.log('Variable', variable)
} else {
console.log('無法存取Variable')
}
console.log(songla)
}
}
</script>
存檔後,ES Lint 會告訴你,無法存取variable
當你拿掉mounted()
裡面的所有程式碼,留下console.log(songla)
,會看到輸出了一個ㄤㄤ
和 f () {}
這是因為test.js export default 的,是一個函式
將console.log(songla)
改成console.log(songla())
,會看到原本輸出的f () {}
變成安安
如果將test.js 的 export default () => {} 改成export {}
export default {
property: 'property value',
someMethod () {
console.log(`call someMethod ${this.property}`)
}
}
<script>
import songla from 'src/lib/test.js'
export default {
name: 'DemoPage',
data () {
return {
}
},
mounted () {
console.log(songla)
console.log(songla.property)
songla.someMethod()
}
}
</script>
你也可以一次import所有被export的變數與函式
一樣會執行test.js裡面,export之外的程式碼
<script>
import * as obj from 'src/lib/test.js'
export default {
name: 'DemoPage',
data () {
return {
}
},
mounted () {
console.log(obj)
}
}
</script>
import之後會以一個物件包住
所有被export的變數與函式:
總結來說,不管你用任何方式import
都會執行被export以外的函式處理,也就是範例中的console.log('ㄤㄤ')
但是無法從外部直接存取
被import的檔案變數,以及直接呼叫被import的檔案的函式
只能先從外部import 有被export的資料後才能存取使用
理解Quasar框架CSS和JS初始化的方式
在架構上可以很方便的規劃和使用
跟Nuxt相比,Quasar並沒有Middleware,可以直接在boot撰寫router.beforeEach
Quasar保留了routes.js的設定彈性,相對的也沒辦法像Nuxt可以產生所有靜態的網頁檔案